package com.cjkj.common.security.interceptor;

import com.alibaba.fastjson2.JSON;
import com.cjkj.common.core.constant.CacheConstants;
import com.cjkj.common.core.constant.SecurityConstants;
import com.cjkj.common.core.utils.ServletUtils;
import com.cjkj.common.core.utils.SpringUtils;
import com.cjkj.common.core.utils.StringUtils;
import com.cjkj.common.core.utils.ip.IpUtils;
import com.cjkj.common.core.web.domain.AjaxResult;
import com.cjkj.common.redis.service.RedisService;
import com.cjkj.common.security.annotation.RepeatSubmit;
import com.cjkj.common.security.utils.SecurityUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 防止重复提交拦截器
 */
public class RepeatSubmitInterceptor implements HandlerInterceptor
{
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
    {
        // 判断处理器对象是否为HandlerMethod类型
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();

            // 获取方法上的RepeatSubmit注解
            RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
            if (annotation != null) {
                // 获取请求的IP地址、URI、请求方法
                String ipAddr = IpUtils.getIpAddr(request);
                String requestURI = request.getRequestURI();
                String requestMethod = request.getMethod();
                String userId = ServletUtils.getHeader(request, SecurityConstants.DETAILS_USER_ID);
                if(StringUtils.isBlank(userId)) {
                    userId = ServletUtils.getHeader(request,SecurityConstants.APP_USER_ID);
                }
                // 创建缓存数据对象，并将请求信息存入其中
                Map<String,Object> cacheData = new HashMap<>();
                cacheData.put("ip", ipAddr);
                cacheData.put("uri", requestURI);
                cacheData.put("method", requestMethod);
                cacheData.put("userId", userId);

                // 将缓存数据进行MD5加密
                String md5V = SecurityUtils.toMD5(JSON.toJSONString(cacheData));

                RedisService redisService = SpringUtils.getBean(RedisService.class);
                // 在Redis缓存中设置缓存对象，如果已存在则返回false
                String key = CacheConstants.REPEAT_SUBMIT_KEY + ipAddr + ":" + md5V;
                if(! redisService.hasKey(key)){
                    // 如果缓存设置成功，则放行请求
                    redisService.setCacheObject(key, cacheData, (long)annotation.interval(), TimeUnit.MILLISECONDS);
                    return true;
                } else {
                    // 如果缓存已存在，则返回重复提交错误信息
                    AjaxResult ajaxResult = AjaxResult.error(annotation.message());
                    ServletUtils.renderString(response, JSON.toJSONString(ajaxResult));
                    return false;
                }
            }

            // 如果方法没有RepeatSubmit注解，则放行请求
            return true;
        }

        return true;
    }
}
